package com.fan.gofast.compent;

import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
 * 批量插入、更新操作
 * @author G7
 */
@Repository
public class BatchRepository<M> {
    protected Log log = LogFactory.getLog(getClass());

    /**
     * 默认批次提交数量
     */
    int DEFAULT_BATCH_SIZE = 1000;


    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdate(Collection<M> entityList,Class<M> entityClazz, Class<M> mapperClazz, DbBatchTypeEnum batchTypeEnum, Integer batchSize) {
        if (Objects.isNull(batchSize)){
            batchSize = DEFAULT_BATCH_SIZE;
        }
        switch (batchTypeEnum) {
            case INSERT:
                return executeBatch(entityClazz, entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(getSqlStatement(mapperClazz, SqlMethod.INSERT_ONE), entity));
            case UPDATE:
                return executeBatch(entityClazz, entityList, batchSize, (sqlSession, entity) -> {
                    MapperMethod.ParamMap<M> param = new MapperMethod.ParamMap<>();
                    param.put(Constants.ENTITY, entity);
                    sqlSession.update(getSqlStatement(mapperClazz, SqlMethod.UPDATE_BY_ID), param);
                });
            default:
                break;
        }
        return false;
    }

    /**
     * 获取mapperStatementId
     *
     * @param sqlMethod 方法名
     * @return 命名id
     * @since 3.4.0
     */
    protected String getSqlStatement(Class<M> mapperClazz,SqlMethod sqlMethod) {
        return SqlHelper.getSqlStatement(mapperClazz, sqlMethod);
    }

    /**
     * 执行批量操作
     *
     * @param list      数据集合
     * @param batchSize 批量大小
     * @param consumer  执行方法
     * @param <E>       泛型
     * @return 操作结果
     * @since 3.3.1
     */
    protected <E> boolean executeBatch(Class<M> entityClazz,Collection<M> list, int batchSize, BiConsumer<SqlSession, M> consumer) {
        return SqlHelper.executeBatch(entityClazz, this.log, list, batchSize, consumer);
    }

}
